home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Languages / Masm V6.11 / SAMPLES / TSR / ALARM.AS$ / ALARM.bin
Encoding:
Text File  |  1993-08-19  |  9.7 KB  |  220 lines

  1. ;* ALARM.ASM - A simple memory-resident program that beeps the speaker
  2. ;* at a prearranged time.  Can be loaded more than once for multiple
  3. ;* alarm settings.  During installation, ALARM establishes a handler
  4. ;* for the timer interrupt (interrupt 08).  It then terminates through
  5. ;* the Terminate-and-Stay-Resident function (function 31h).  After the
  6. ;* alarm sounds, the resident portion of the program retires by setting
  7. ;* a flag that prevents further processing in the handler.
  8.  
  9.         .MODEL tiny                     ; Create ALARM.COM
  10.         .STACK
  11.  
  12.         .CODE
  13.  
  14.         ORG     5Dh                     ; Location of time argument in PSP,
  15. CountDown       LABEL   WORD            ;   converted to number of 5-second
  16.                                         ;   intervals to elapse
  17.         .STARTUP
  18.         jmp     Install                 ; Jump over data and resident code
  19.  
  20. ; Data must be in code segment so it won't be thrown away with Install code.
  21.  
  22. OldTimer        DWORD   ?               ; Address of original timer routine
  23. tick_91         BYTE    91              ; Counts 91 clock ticks (5 seconds)
  24. TimerActiveFlag BYTE    0               ; Active flag for timer handler
  25. Error_msg    BYTE    0dh,0ah
  26.         BYTE    'The time must be between 0000 and 2359 !'
  27.         BYTE    0dh,0ah,'$'
  28.  
  29.  
  30. ;* NewTimer - Handler routine for timer interrupt (interrupt 08).
  31. ;* Decrements CountDown every 5 seconds.  No other action is taken
  32. ;* until CountDown reaches 0, at which time the speaker sounds.
  33.  
  34. NewTimer PROC   FAR
  35.  
  36.         .IF     cs:TimerActiveFlag != 0 ; If timer busy or retired,
  37.         jmp     cs:OldTimer             ;   jump to original timer routine
  38.         .ENDIF
  39.         inc     cs:TimerActiveFlag      ; Set active flag
  40.         pushf                           ; Simulate interrupt by pushing flags,
  41.         call    cs:OldTimer             ;   then far-calling original routine
  42.         sti                             ; Enable interrupts
  43.         push    ds                      ; Preserve DS register
  44.         push    cs                      ; Point DS to current segment for
  45.         pop     ds                      ;   further memory access
  46.         dec     tick_91                 ; Count down for 91 ticks
  47.         .IF     zero?                   ; If 91 ticks have elapsed,
  48.         mov     tick_91, 91             ;   reset secondary counter and
  49.         dec     CountDown               ;   subtract one 5-second interval
  50.         .IF     zero?                   ; If CountDown drained,
  51.         call    Sound                   ;   sound speaker
  52.         inc     TimerActiveFlag         ; Alarm has sounded, set flag
  53.         .ENDIF
  54.         .ENDIF
  55.  
  56.         dec     TimerActiveFlag         ; Decrement active flag
  57.         pop     ds                      ; Recover DS
  58.         iret                            ; Return from interrupt handler
  59.  
  60. NewTimer ENDP
  61.  
  62.  
  63. ;* Sound - Sounds speaker with the following tone and duration:
  64.  
  65. BEEP_TONE       EQU     440             ; Beep tone in hertz
  66. BEEP_DURATION   EQU     6               ; Number of clocks during beep,
  67.                                         ;   where 18 clocks = approx 1 second
  68.  
  69. Sound   PROC    USES ax bx cx dx es     ; Save registers used in this routine
  70.         mov     al, 0B6h                ; Initialize channel 2 of
  71.         out     43h, al                 ;   timer chip
  72.         mov     dx, 12h                 ; Divide 1,193,180 hertz
  73.         mov     ax, 34DCh               ;   (clock frequency) by
  74.         mov     bx, BEEP_TONE           ;   desired frequency
  75.         div     bx                      ; Result is timer clock count
  76.         out     42h, al                 ; Low byte of count to timer
  77.         mov     al, ah
  78.         out     42h, al                 ; High byte of count to timer
  79.         in      al, 61h                 ; Read value from port 61h
  80.         or      al, 3                   ; Set first two bits
  81.         out     61h, al                 ; Turn speaker on
  82.  
  83. ; Pause for specified number of clock ticks
  84.  
  85.         mov     dx, BEEP_DURATION       ; Beep duration in clock ticks
  86.         sub     cx, cx                  ; CX:DX = tick count for pause
  87.         mov     es, cx                  ; Point ES to low memory data
  88.         add     dx, es:[46Ch]           ; Add current tick count to CX:DX
  89.         adc     cx, es:[46Eh]           ; Result is target count in CX:DX
  90.         .REPEAT
  91.         mov     bx, es:[46Ch]           ; Now repeatedly poll clock
  92.         mov     ax, es:[46Eh]           ;   count until the target
  93.         sub     bx, dx                  ;   time is reached
  94.         sbb     ax, cx
  95.         .UNTIL  !carry?
  96.  
  97.         in      al, 61h                 ; When time elapses, get port value
  98.         xor     al, 3                   ; Kill bits 0-1 to turn
  99.         out     61h, al                 ;   speaker off
  100.         ret
  101.  
  102. Sound   ENDP
  103.  
  104.  
  105.  
  106. ;* Install - Converts ASCII argument to valid binary number, replaces
  107. ;* NewTimer as the interrupt handler for the timer, then makes program
  108. ;* memory resident by exiting through function 31h.
  109. ;*
  110. ;* This procedure marks the end of the TSR's resident section and the
  111. ;* beginning of the installation section.  When ALARM terminates through
  112. ;* function 31h, the above code and data remain resident in memory.  The
  113. ;* memory occupied by the following code is returned to DOS.
  114.  
  115.  
  116. Install PROC
  117.  
  118. ; Time argument is in hhmm military format.  Convert ASCII digits to
  119. ; number of minutes since midnight, then convert current time to number
  120. ; of minutes since midnight.  Difference is number of minutes to elapse
  121. ; until alarm sounds.  Convert to seconds-to-elapse, divide by 5 seconds,
  122. ; and store result in word CountDown.
  123.  
  124. DEFAULT_TIME    EQU     3600            ; Default alarm setting = 1 hour
  125.                                         ;   (in seconds) from present time
  126.         mov     ax, DEFAULT_TIME
  127.         cwd                             ; DX:AX = default time in seconds
  128.  
  129.  
  130.     sub    bx,bx            ; Check if there is only numbers
  131.     .REPEAT
  132.     cmp    BYTE PTR CountDown[bx],'0'
  133.     jb    time_err
  134.     cmp    BYTE PTR CountDown[bx],'9'
  135.     ja    time_err
  136.     inc    bx
  137.     .UNTIL    (bx == 4)
  138.  
  139.  
  140.         xor     CountDown[0], '00'      ;   convert 4 bytes of ASCII
  141.         xor     CountDown[2], '00'      ;   argument to binary
  142.                                         
  143.         mov     al, 10                  ; Multiply 1st hour digit by 10
  144.         mul     BYTE PTR CountDown[0]   ;   and add to 2nd hour digit
  145.         add     al, BYTE PTR CountDown[1]
  146.         mov     bh, al                  ; BH = hour for alarm to go off
  147.         mov     al, 10                  ; Repeat procedure for minutes
  148.         mul     BYTE PTR CountDown[2]   ; Multiply 1st minute digit by 10
  149.         add     al, BYTE PTR CountDown[3] ;   and add to 2nd minute digit
  150.         mov     bl, al                  ; BL = minute for alarm to go off
  151.  
  152.  
  153.     cmp     bh,23              ; Check if hour <=23
  154.     jg    time_err
  155.     cmp    bl,59              ; Check if minute <=59
  156.     jnge    time_ok
  157.  
  158. time_err:
  159.     mov    dx,offset Error_msg    ; Print Error_msg
  160.     mov    ah,9
  161.     int    21h
  162.     .exit                ; exit and don't install
  163.  
  164.  
  165. time_ok:
  166.         mov     ah, 2Ch                 ; Request function 2Ch
  167.         int     21h                     ; Get Time (CX = current hour/min)
  168.         mov     dl, dh
  169.         sub     dh, dh
  170.         push    dx                      ; Save DX = current seconds
  171.  
  172.         mov     al, 60                  ; Multiply current hour by 60
  173.         mul     ch                      ;   to convert to minutes
  174.         sub     ch, ch
  175.         add     cx, ax                  ; Add current minutes to result
  176.                                         ; CX = minutes since midnight
  177.         mov     al, 60                  ; Multiply alarm hour by 60
  178.         mul     bh                      ;   to convert to minutes
  179.         sub     bh, bh
  180.         add     ax, bx                  ; AX = number of minutes since
  181.                                         ;   midnight for alarm setting
  182.         sub     ax, cx                  ; AX = time in minutes to elapse
  183.                                         ;   before alarm sounds
  184.         .IF     carry?                  ; If alarm time is tomorrow,
  185.         add     ax, 24 * 60             ;   add minutes in a day
  186.         .ENDIF
  187.  
  188.         mov     bx, 60
  189.         mul     bx                      ; DX:AX = minutes-to-elapse-times-60
  190.         pop     bx                      ; Recover current seconds
  191.         sub     ax, bx                  ; DX:AX = seconds to elapse before
  192.         sbb     dx, 0                   ;   alarm activates
  193.         .IF     carry?                  ; If negative,
  194.         mov     ax, 5                   ;   assume 5 seconds
  195.         cwd
  196.         .ENDIF
  197.  
  198.         mov     bx, 5                   ; Divide result by 5 seconds
  199.         div     bx                      ; AX = number of 5-second intervals
  200.         mov     CountDown, ax           ;   to elapse before alarm sounds
  201.  
  202.         mov     ax, 3508h               ; Request function 35h
  203.         int     21h                     ; Get vector for timer (interrupt 08)
  204.         mov     WORD PTR OldTimer[0], bx; Store address of original
  205.         mov     WORD PTR OldTimer[2], es;   timer interrupt
  206.         mov     ax, 2508h               ; Request function 25h
  207.         mov     dx, OFFSET NewTimer     ; DS:DX points to new timer handler
  208.         int     21h                     ; Set vector with address of NewTimer
  209.  
  210.         mov     dx, OFFSET Install      ; DX = bytes in resident section
  211.         mov     cl, 4
  212.         shr     dx, cl                  ; Convert to number of paragraphs
  213.         inc     dx                      ;   plus one
  214.         mov     ax, 3100h               ; Request function 31h, error code=0
  215.         int     21h                     ; Terminate-and-Stay-Resident
  216.  
  217. Install ENDP
  218.  
  219.         END
  220.